// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/app_list/views/search_result_tile_item_list_view.h"

#include <stddef.h>

#include "base/i18n/rtl.h"
#include "ui/app_list/app_list_constants.h"
#include "ui/app_list/app_list_view_delegate.h"
#include "ui/app_list/search_result.h"
#include "ui/app_list/views/search_result_tile_item_view.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/box_layout.h"

namespace {

// Layout constants.
const size_t kNumSearchResultTiles = 5;
const int kTileSpacing = 7;
const int kTopBottomPadding = 8;

} // namespace

namespace app_list {

SearchResultTileItemListView::SearchResultTileItemListView(
    views::Textfield* search_box,
    AppListViewDelegate* view_delegate)
    : search_box_(search_box)
{
    SetLayoutManager(
        new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, kTileSpacing));
    for (size_t i = 0; i < kNumSearchResultTiles; ++i) {
        SearchResultTileItemView* tile_item = new SearchResultTileItemView(this, view_delegate);
        tile_item->SetParentBackgroundColor(kCardBackgroundColor);
        tile_item->SetBorder(views::Border::CreateEmptyBorder(
            kTopBottomPadding, 0, kTopBottomPadding, 0));
        tile_views_.push_back(tile_item);
        AddChildView(tile_item);
    }
}

SearchResultTileItemListView::~SearchResultTileItemListView()
{
}

void SearchResultTileItemListView::OnContainerSelected(
    bool from_bottom,
    bool directional_movement)
{
    if (num_results() == 0)
        return;

    // If the user came from below using linear controls (eg, Tab, as opposed to
    // directional controls such as Up), select the right-most result. Otherwise,
    // select the left-most result even if coming from below.
    bool select_last = from_bottom && !directional_movement;
    SetSelectedIndex(select_last ? num_results() - 1 : 0);
}

void SearchResultTileItemListView::NotifyFirstResultYIndex(int y_index)
{
    for (size_t i = 0; i < static_cast<size_t>(num_results()); ++i)
        tile_views_[i]->result()->set_distance_from_origin(i + y_index);
}

int SearchResultTileItemListView::GetYSize()
{
    return num_results() ? 1 : 0;
}

int SearchResultTileItemListView::Update()
{
    std::vector<SearchResult*> display_results = AppListModel::FilterSearchResultsByDisplayType(
        results(), SearchResult::DISPLAY_TILE, kNumSearchResultTiles);
    for (size_t i = 0; i < kNumSearchResultTiles; ++i) {
        SearchResult* item = i < display_results.size() ? display_results[i] : nullptr;
        tile_views_[i]->SetSearchResult(item);
    }

    set_container_score(
        display_results.empty() ? 0 : display_results.front()->relevance());

    return display_results.size();
}

void SearchResultTileItemListView::UpdateSelectedIndex(int old_selected,
    int new_selected)
{
    if (old_selected >= 0)
        tile_views_[old_selected]->SetSelected(false);

    if (new_selected >= 0)
        tile_views_[new_selected]->SetSelected(true);
}

bool SearchResultTileItemListView::OnKeyPressed(const ui::KeyEvent& event)
{
    if (selected_index() >= 0 && child_at(selected_index())->OnKeyPressed(event))
        return true;

    int dir = 0;
    bool cursor_at_end_of_searchbox = search_box_->GetCursorPosition() == search_box_->text().length();
    const int forward_dir = base::i18n::IsRTL() ? -1 : 1;
    switch (event.key_code()) {
    case ui::VKEY_TAB:
        if (event.IsShiftDown())
            dir = -1;
        else
            dir = 1;
        break;
    case ui::VKEY_LEFT:
        // The left key will not capture the key event when the selection is at
        // the beginning of the list. This means that the text cursor in the
        // search box will be allowed to handle the keypress. This will also
        // ignore the keypress if the user has clicked somewhere in the middle of
        // the searchbox.
        if (cursor_at_end_of_searchbox)
            dir = -forward_dir;
        break;
    case ui::VKEY_RIGHT:
        // Only move right if the search box text cursor is at the end of the
        // text.
        if (cursor_at_end_of_searchbox)
            dir = forward_dir;
        break;
    default:
        break;
    }
    if (dir == 0)
        return false;

    int selection_index = selected_index() + dir;
    if (IsValidSelectionIndex(selection_index)) {
        SetSelectedIndex(selection_index);
        return true;
    }

    return false;
}

} // namespace app_list
